{{!

  Copyright (c) Meta Platforms, Inc. and affiliates.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

}}
# @{{!}}generated
from __future__ import annotations

import typing
import typing as _typing

from common.thrift.patch.detail.dynamic_patch import (
    BaseStructPatch,
    BaseUnionPatch,
    ListPatch,
    SetPatch,
    MapPatch,
    OptionalFieldPatch,
    UnqualifiedFieldPatch,
)

from common.thrift.patch.detail.py_bindings.DynamicPatch import (
    BoolPatch,
    BytePatch,
    I16Patch,
    I32Patch,
    I64Patch,
    FloatPatch,
    DoublePatch,
    StringPatch,
    BinaryPatch,
    StructPatch as DynamicStructPatch,
    UnionPatch as DynamicUnionPatch,
    DynamicPatch,
    EnumPatch
)

import thrift.python.types as _fbthrift_python_types
import folly.iobuf as _fbthrift_iobuf

import {{program:module_path}}.thrift_types as {{program:module_mangle}}__thrift_types
{{#if (not program:safe_patch?)}}
import {{program:safe_patch_module_path}}.thrift_types as _fbthrift_safe_patch_types
{{/if (not program:safe_patch?)}}

{{#program:include_namespaces}}
{{#if has_types?}}{{#if (not is_patch?)}}{{#if needed_by_patch?}}

import {{included_module_path}}.{{> ../python/types/types_import_path}} as {{included_module_mangle}}__{{> ../python/types/types_import_path}}
import {{included_module_path}}.thrift_patch
{{/if needed_by_patch?}}{{/if (not is_patch?)}}{{/if has_types?}}
{{/program:include_namespaces}}

{{#program:structs}}

class {{struct:py_name}}Patch(
    Base{{#if struct:union?}}Union{{#else}}Struct{{/if struct:union?}}Patch[{{program:module_mangle}}__thrift_types.{{struct:py_name}}]
):
    pass
    {{#struct:fields_ordered_by_id}}{{#field:type}}{{#if (not type:contains_patch?)}}
    @property
    def {{field:py_name}}(self) -> {{> types/field_patch_type}}[
            {{> ../python/types/unadapted_pep484_type}},
            {{> ../python/types/unadapted_pep484_patch_type}}]:

        {{! e.g., if field is an i32, this function convert DynamicPatch --> I32Patch }}
        def cast_dynamic_patch_to_typed_field_patch(patch: DynamicPatch, type_info) -> {{> ../python/types/unadapted_pep484_patch_type}}:
            {{> ../python/common/thrift_patch_callback}}

        return {{> types/field_patch_type}}(
            cast_dynamic_patch_to_typed_field_patch,
            self._patch,
            {{field:id}},
            {{> ../python/types/typeinfo }})
    {{/if (not type:contains_patch?)}}{{/field:type}}{{/struct:fields_ordered_by_id}}
    {{#if (not program:safe_patch?)}}{{! If the program is already a safe patch, we should not generate to_safe_patch/from_safe_patch, otherwise it becomes a safe patch of safe patch}}

    def to_safe_patch(self) -> _fbthrift_safe_patch_types.{{struct:name}}SafePatch:
        return _fbthrift_safe_patch_types.{{struct:name}}SafePatch(
            version=1, data=self._patch.serialize_to_compact_protocol()
        )

    @staticmethod
    def from_safe_patch(safe_patch: _fbthrift_safe_patch_types.{{struct:name}}SafePatch) -> {{struct:py_name}}Patch:
        patch = {{struct:py_name}}Patch()
        DynamicPatch = Dynamic{{#if struct:union?}}Union{{#else}}Struct{{/if struct:union?}}Patch
        patch._patch = DynamicPatch.deserialize_from_compact_protocol(safe_patch.data)
        return patch
    {{/if (not program:safe_patch?)}}

    def merge(self, other: {{struct:py_name}}Patch) -> None:
        self._patch.merge(other._patch)

{{/program:structs}}
